﻿using System;
using System.Text;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using IntraVision.Web;
using IntraVision.Web.Security;
using Model;

/// <summary>
/// Summary description for TimeReportController
/// </summary>
[AllowedRole("Finance", "TimeReport")]
public class TimeReportController : ReportController<NotarialServiceDataContext>
{
    const string emptyTimeCaption = "-----";
    DateTime _StartDate;
    DateTime _EndDate;
    int _UserId;
    protected string[] _Columns;

    public TimeReportController():base()
    {
        /*
        _StartDate = new DateTime(DateTime.Now.Year, DateTime.Now.AddMonths(-1).Month, 1);
        _EndDate = DateTime.Now.AddDays(-DateTime.Now.Day);*/
        _StartDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
        _EndDate = new DateTime(DateTime.Now.Year, DateTime.Now.AddMonths(1).Month, 1).AddDays(-1);
        _UserId = 0;
        _isCalculateTotal = true;
        _Columns = new string[6] { "UserId", "UserName", "Date", "StartTime", "EndTime", "SummaryTime" };
        _ColumnsCaptions = new string[6] { "UserId", "UserName", "Дата", "Время прихода", "Время ухода", "Часов" };
    }

    public override void Default()
    {
        if (_isExcel)
            TemplatePath = "~/views/timereport/_table.haml";

        InitDatesFromRequest();

        ViewData["months"] = GetMonthList();
        ViewData["years"] = GetYearsList(DateTime.Now.Year, 10);
        ViewData["users"] = GetUsersList();

        base.Default();
    }

    protected void InitDatesFromRequest()
    {
        DateTime bufDateTime;
        int bufUserId;
        if (!String.IsNullOrEmpty(Request["startdate"]) && DateTime.TryParse(Request["startdate"], out bufDateTime))
        {
            _StartDate = bufDateTime;
            ViewData["currentYear"] = _StartDate.Year;
            ViewData["currentMonth"] = _StartDate.Month;
        }
        if (!String.IsNullOrEmpty(Request["enddate"]) && DateTime.TryParse(Request["enddate"], out bufDateTime))
            _EndDate = bufDateTime;
        if (!String.IsNullOrEmpty(Request["userid"]) && Int32.TryParse(Request["userid"], out bufUserId))
            _UserId = bufUserId;
            
    }

    protected override void InitParams(NotarialServiceDataContext dc)
    {
        //подкорректируем диапазон дат, чтобы учесть крайние границы времени
        _StartDate = _StartDate.AddHours(-_StartDate.Hour);
        _StartDate = _StartDate.AddMinutes(-_StartDate.Minute);
        _EndDate = _EndDate.AddHours(-_EndDate.Hour + 23);
        _EndDate = _EndDate.AddMinutes(-_EndDate.Minute + 59);

        //добавим параметры
        _CommandParams.Clear();
        _CommandParams.Add("@StartDate", _StartDate);
        _CommandParams.Add("@EndDate", _EndDate);
        _CommandParams.Add("@UserId", _UserId);
    }

    protected override void DataReceived(DataSet ds)
    {
        base.DataReceived(ds);

        ViewData["startdate"] = _StartDate;
        ViewData["enddate"] = _EndDate;
        ViewData["userId"] = _UserId;
    }

    protected override void PrepareDataTable(ref DataTable dt)
    {        
        int currentUserId, operation, userId = 0;
        DateTime currentDate, date = new DateTime();
        EventLogOperationType lastOperation = 0;

        var resultTable = CreateResultTable();

        DataRow row = resultTable.NewRow();
        foreach (DataRow dr in dt.Rows)
        {
            currentUserId = Convert.ToInt32(dr["UserId"]);
            currentDate = Convert.ToDateTime(dr["DateOnly"]);

            //добавляем новый ряд, если новый пользователь или новая дата или это первый раз
            if (currentUserId != userId || userId == 0 || currentDate != date || date == DateTime.MinValue)
            {
                row = resultTable.NewRow();
                resultTable.Rows.Add(row);

                date = currentDate;
                row["Date"] = date.ToDateString();

                row["UserId"] = userId = currentUserId;
                row["UserName"] = dr["UserName"];                             
            }

            //определяем тип операции (вход или выход)
            operation = Convert.ToInt32(dr["OperationId"]);
            switch ((EventLogOperationType)operation)
            {
                case EventLogOperationType.UserLogin:
                    {
                        row["StartTime"] = dr["TimeOnly"];
                        break;
                    }
                case EventLogOperationType.UserLogout:
                    {
                        row["EndTime"] = dr["TimeOnly"];
                        break;
                    }
            }        
        }

        CalculateTimeSummary(ref resultTable);

        dt = resultTable;

        SetColumnsCaption(ref dt);
    }

    private DataTable CreateResultTable()
    {
        var result = new DataTable();

        foreach(var c in _Columns)       
            result.Columns.Add(c);
        return result;
    }

    private void CalculateTimeSummary(ref DataTable dt)
    {
        foreach (DataRow dr in dt.Rows)
            dr["SummaryTime"] = (!CheckEmptyValue(dr, "StartTime") && !CheckEmptyValue(dr, "EndTime")) 
                ? CalculateTimeSummary(dr["StartTime"].ToString(), dr["EndTime"].ToString())
                : emptyTimeCaption;
    }

    private bool CheckEmptyValue(DataRow dr, string columnName)
    {
        if (string.IsNullOrEmpty(dr[columnName] as string))
        {
            dr[columnName] = emptyTimeCaption;
            return true;
        }
        return false;
    }

    private string CalculateTimeSummary(string startTime, string endTime)
    {
        var sTime = TimeSpan.Parse(startTime);
        var eTime = TimeSpan.Parse(endTime);
        return FormatTime(eTime.Subtract(sTime));    
    }

    private string FormatTime(TimeSpan time)
    {
        var sb = new StringBuilder();
        if (time.Hours > 0) sb.AppendFormat("{0} ч ", time.Hours);
        sb.AppendFormat("{0} мин", (time.Minutes > 0) ? time.Minutes : 1);
        return sb.ToString();
    }

    protected object GetUsersList()
    {
        object users;
        using (var dc = new NotarialServiceDataContext())
        {
            users = (from u in dc.Users orderby u.LastName select new { Id = u.Id, Name = u.FullName }).ToList();
        }
        return users;
    }
}
